package jvm.VMExecSubsystem;

/**
 * @author msi
 *  -verbose:gc
 */
public class SlotReUseImpactGC {
    /**
     * 局部变量表槽复用对垃圾收集器的影响之一
     */
    public static void main1(String[] args) {
        byte[] placeholder = new byte[64 * 1024 * 1024]; //64M
        System.gc();
    }
    /**
     * 结果： 没有回收这64M的空间，这是正常的，毕竟GC Roots对象直接引用到这个数组。
     */


    /**
     * 局部变量表槽复用对垃圾收集器的影响之二
     */
    public static void main2(String[] args) {
        {
            byte[] placeholder = new byte[64 * 1024 * 1024]; //64M
        }
        System.gc();
    }
    /**
     * 结果： 依然没有回收这64M的空间，按照局部变量表的复用原则，到gc()调用的时候已经出了placeholder的作用域了，应该对其复用了，可以回收这个内存空间啊。
     * 这是为什么呢？
     */


    /**
     * 局部变量表槽复用对垃圾收集器的影响之三
     */
    public static void main3(String[] args) {
        {
            byte[] placeholder = new byte[64 * 1024 * 1024]; //64M
        }
        int a=0;
        System.gc();
    }
    /**
     * 结果： 回收了这64M的空间，
     */

    /**
     * 局部变量表槽复用对垃圾收集器的影响之三
     */
    public static void main(String[] args) {
        {
            byte[] placeholder = new byte[64 * 1024 * 1024]; //64M
            byte[] placeholder1 = new byte[64 * 1024 * 1024]; //64M
        }
        int a=0;//替代一个数组内存
//        int b=0;//替代另一个数组内存
        System.gc();
    }
    /**
     * 结果： 只回收了这64M的空间，
     */

    /**
     * 解释：虽然在第二个例子中这个数组已经没有被使用了，但是当前局部变量表中还是存放的这个数组(即GC Roots还是关联到这个对象的)所以不会回收，在第三，四个例子中，显示如果之后有新的对象赋值，那么就会替换掉相应的局部变量表内存值，
     * 一对一替换，如第四个例子所示。在《Practical Java》一书中有一条建议"不使用的对象应手动赋值为null"，zzm对其有不同的看法。
     * 将其赋值为null可以使该对象顺利的被回收，但是在当前的JDK版本来看，这种方式不一定可行了，由于即时编译器的优化，这条赋值为null的语句在经过即时编译器之后一定会被当作无效代码消除掉。这时候的赋值是毫无意义的。
     * 并且在第二个例子经过即时编译后，就已经可以正常回收了，不需要写出3或4的形式。
     * 关于局部变量表还有一点和类变量不同，就是它是不会初始化的，使用局部变量表中的变量必须自己初始化，不然会出错。
     */
}
